package g_jackson;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

/**
 * Json工具类
 * @author Y
 *
 */
/** 
 * ObjectMapper是JSON操作的核心，Jackson的所有JSON操作都是在ObjectMapper中实现。 
 * ObjectMapper有多个JSON序列化的方法，可以把JSON字符串保存File、OutputStream等不同的介质中。 
 * writeValue(File arg0, Object arg1)把arg1转成json序列，并保存到arg0文件中。 
 * writeValue(OutputStream arg0, Object arg1)把arg1转成json序列，并保存到arg0输出流中。 
 * writeValueAsBytes(Object arg0)把arg0转成json序列，并把结果输出成字节数组。 
 * writeValueAsString(Object arg0)把arg0转成json序列，并把结果输出成字符串。 
 */  

/**
 * Jackson提供了一系列注解，方便对JSON序列化和反序列化进行控制，下面介绍一些常用的注解。
 *@JsonIgnore 此注解用于属性上，作用是进行JSON操作时忽略该属性。
 *@JsonFormat 此注解用于属性上，作用是把Date类型直接转化为想要的格式，如@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")。
 *@JsonProperty 此注解用于属性上，作用是把该属性的名称序列化为另外一个名称，如把trueName属性序列化为name，@JsonProperty("name")。
 */
public class JsonUtil {

	final static Logger logger = LoggerFactory.getLogger(JsonUtil.class);
	private final static String TIME_ZONE = "GMT+8";
	private final static String timePattern = "yyyy-MM-dd HH:mm:ss";
	
	/**
	 *转成Json字符串
	 * @param object	转换对象
	 * @param outputEmpty 是否输出为空值
	 * @return	
	 */
	public static String toJsonString(Object object){
		return toJsonString(object,false);
	}
	
	/**
	 * 转成Json字符串
	 * @param object		
	 * @param outputEmpty	是否输出空值
	 * @return
	 */
	private static String toJsonString(Object object, boolean outputEmpty) {
		if (object != null) {
			try {
				return creatObjectMapper(outputEmpty,timePattern).writeValueAsString(object);
			} catch (IOException e) {
				logger.error("Json格式化异常",e);
			}
		}
		return null;
	}

	public static <T> T readJson2Bean(String jsonString,boolean outputEmpty, String timePattern,Class<T> valueType){
		if (StringUtils.isNotBlank(jsonString)) {
			try {
				return creatObjectMapper(outputEmpty, timePattern).readValue(jsonString, valueType);
			} catch (IOException e) {
				logger.error("Json格式化异常",e);
			}
		}
		return null;
	}
	
	
	public static <T> T readJson2Bean(String jsonString, boolean outputEmpty, String timePattern, TypeReference ref){
		if (outputEmpty) {
			try {
				return creatObjectMapper(outputEmpty, timePattern).readValue(jsonString, ref);
			} catch (IOException e) {
				 logger.error("Json格式化异常", e);
			}
		}
		return null;
	}
	
	public static <T> List<T> readJson2List(String jsonString, boolean outputEmpty, String timePattern, Class<T> elementClass){
		if (StringUtils.isNotBlank(jsonString)) {
			try {
				ObjectMapper mapper = creatObjectMapper(outputEmpty, timePattern);
				return mapper.readValue(jsonString, mapper.getTypeFactory().constructCollectionLikeType(List.class, elementClass));
			} catch (IOException e) {
				logger.error("Json格式化异常", e);
			}
		}
		return null;
	}
	
	/**
	 * 对象转换
	 * @param fromValue	输入对象
	 * @param toValueType	输出对象
	 * @return
	 */
	public static <T> T convertValue(Object fromValue,Class<T> toValueType){
		return creatObjectMapper(false, timePattern).convertValue(fromValue, toValueType);
	}
	
	/**
	 * 对象转换
	 * @param fromValue			输入对象
	 * @param toValueTypeRef	输出对象
	 * @return
	 */
	public static <T> T convertValue(Object fromValue, TypeReference<T> toValueTypeRef){
		return creatObjectMapper(false, timePattern).convertValue(fromValue, toValueTypeRef);
	}
	
	
	/**
	 * 创建ObjcetMapper对象
	 * @param outputEmpty 是否输出空
	 * @param timePattern 时间格式化
	 * @return
	 */
	private static ObjectMapper creatObjectMapper(boolean outputEmpty,
			String timePattern) {
		ObjectMapper mapper = new ObjectMapper();
		if (!outputEmpty) {
			mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);	//不输出空值
		}
		if (StringUtils.isNoneBlank(timePattern)) {
			mapper.setDateFormat(new SimpleDateFormat(timePattern));
		}
		mapper.setTimeZone(TimeZone.getTimeZone(TIME_ZONE));
		//Json字符串格式化
//		mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
//		
//		mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
		//允许序列化空的对象,比如Object
		mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
		//忽略在JSON字符串中存在,但在Java对象时间没有属性
		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		
		return mapper;
	}
	
	
	public static void main(String[] args) {
		User user = new User();
		user.setName("dandan");
		user.setAge(20);
		user.setEmail("dandandan");
		SimpleDateFormat sdf = new SimpleDateFormat(timePattern);
		try {
			user.setBirthday(sdf.parse("1997-11-16 00:00:00"));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		ArrayList<User> users = new ArrayList<User>();
		users.add(user);
		System.out.println(JsonUtil.toJsonString(user));
		System.out.println(JsonUtil.toJsonString(users));
		
		String jsonString ="{\"name\":\"dandan\",\"age\":20,\"birthday\":\"1997-11-16 00:00:00\",\"email\":\"dandandan\"}";
		String jsonStrings="[{\"name\":\"dandan\",\"age\":20,\"birthday\":\"1997-11-16 00:00:00\",\"email\":\"dandandan\"}]";
		
		User userj=JsonUtil.readJson2Bean(jsonString, false, timePattern, User.class);
		System.out.println("json转对象"+userj.toString());
		
		List<User> usersj=JsonUtil.readJson2List(jsonStrings, false, timePattern, User.class);
		System.out.println("json转集合"+usersj.toString());
		
		Map<String,List<User>> map=new HashMap<>();
		map.put("users", usersj);
		System.out.println(JsonUtil.toJsonString(map));
	
	}
}
